package com.warrior.superdata.handler;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.warrior.superdata.constants.CommonConstant;
import com.warrior.superdata.constants.ResultCode;
import com.warrior.superdata.base.BasePageResultVo;
import com.warrior.superdata.exceptionhandler.ApplicationException;
import com.warrior.superdata.mysql.entity.dto.ApiInfoDetailDto;
import com.warrior.superdata.mysql.entity.dto.ApiResultDto;
import com.warrior.superdata.mysql.entity.dto.ExcelDataDto;
import com.warrior.superdata.util.DateUtils;
import com.warrior.superdata.util.ExcelUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import javax.servlet.http.HttpServletResponse;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description:
 * @ClassName: ExportHandler.java
 * @date: 2022/3/10 14:51
 * @author xujian
 */
@Component
@Slf4j
public class ExportHandler {

    public void export(HttpServletResponse response, ApiInfoDetailDto apiInfoDetailDto, Object data) {
        List<String> titles = apiInfoDetailDto.getResults().stream().filter(item ->
                StringUtils.isNotBlank(item.getExportName())
        ).map(ApiResultDto::getExportName).collect(Collectors.toList());

        List<String> titleNames = apiInfoDetailDto.getResults().stream().filter(item ->
                StringUtils.isNotBlank(item.getExportName())
        ).map(ApiResultDto::getResultName).collect(Collectors.toList());

        if (CollectionUtils.isEmpty(titles)) {
            throw new ApplicationException(ResultCode.FAIL_CODE, "导出列不能为空");
        }

        ExcelDataDto excelDataDto = new ExcelDataDto();
        List<List<Object>> rows = new ArrayList<>();
        if (data instanceof JSONObject) {
            List row = handlerRow(data, titleNames);
            rows.add(row);
        } else if (data instanceof JSONArray) {
            ((JSONArray) data).forEach(item -> {
                List row = handlerRow(item, titleNames);
                rows.add(row);
            });
        } else if (data instanceof BasePageResultVo) {
            Object content = ((BasePageResultVo<?>) data).getContent();
            if (content instanceof List) {
                ((List) content).forEach(item -> {
                    List row = handlerRow(item, titleNames);
                    rows.add(row);
                });
            }
        }

        excelDataDto.setRows(rows);
        excelDataDto.setTitles(titles);

        XSSFWorkbook wb = ExcelUtil.generateWb(excelDataDto);
        String dateTime = DateUtils.convertDateToString(new Date(), CommonConstant.CONSTANT_DATENUM_FORMAT);
        String fileName = dateTime + "-file.xlsx";
        response.setContentType("application/vnd.ms-excel");
        response.setCharacterEncoding("utf-8");
        response.setHeader("Content-disposition", "attachment;filename=" + fileName);

        OutputStream outputStream = null;
        BufferedOutputStream bufferedOutputStream = null;
        try {
            outputStream = response.getOutputStream();
            bufferedOutputStream = new BufferedOutputStream(outputStream);
            bufferedOutputStream.flush();
            wb.write(bufferedOutputStream);
        } catch (Exception e) {
            log.error("导出文件异常 errMsg:{}", e.getMessage());
        } finally {
            try {
                if (null != bufferedOutputStream) {
                    bufferedOutputStream.close();
                }
                if (null != outputStream) {
                    outputStream.close();
                }
                if (null != wb) {
                    wb.close();
                }
            } catch (IOException e) {
                log.error("导出文件关流异常 errMsg:{}", e.getMessage());
            }
        }
    }

    private List handlerRow(Object item, List<String> titles) {
        List<Object> row = new ArrayList<>();
        Set<String> keys = ((JSONObject) item).keySet();
        titles.forEach(title -> {
            keys.forEach(key -> {
                if (title.equals(key)) {
                    row.add(((JSONObject) item).get(key));
                }
            });
        });

        return row;
    }

}
